pub mod entity;
pub mod learn;
pub mod utils;

use std::time::Duration;
use std::{self, thread};

use entity::user_info::UserInfo;
use entity::user_info::save;
use entity::user_info::delete_by_id;
use entity::user_info::update_by_id;
use entity::user_info::check_login;
use entity::user_info::query_all;
use entity::user_info::query_by_id;

use utils::system::os;
use utils::system::COUNT;
use learn::first::show_os;

use std::sync::{Arc, Mutex};
use regex::Regex;

use rustc_serialize::json;

use std::collections::HashMap;

static FILE_NAME: &str = "main";

fn check_username(user_name: String) {
    match user_name {
        _ if user_name == "admin" => println!("超级管理员"),
        _ if user_name == "allnas" => println!("管理员"),
        _ => println!("访客"),
    }
}

fn check_username2(user_name: String) {
    match Some(String::from(user_name)) {
        Some(ref x) if x == "admin" => println!("超级管理员"),
        Some(ref x) if x == "allnas" => println!("管理员"),
        Some(_x) => println!("unkown"),
        None => println!("访客"),
    }
}

#[allow(dead_code)]
fn regex() -> bool {
    let re = Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap();
    return re.is_match("2019-10-10");
}

fn hashmap() {
    let mut maps = HashMap::new();
    maps.insert(String::from("username"), String::from("李小龙"));
    maps.insert(String::from("username"), String::from("成龙"));//存在即覆盖
    maps.entry(String::from("username")).or_insert(String::from("李连杰"));//存在跳过、不存在添加
    maps.entry(String::from("job")).or_insert(String::from("动作巨星"));

    for (key, value) in &maps {
        println!("{}: {}", key, value);
    }
}

#[allow(dead_code)]
fn object() {
    let mut x: u32 = 10;
    let y = {
        x = x + 1;
        10
    };
    println!("x:{}", x);
    println!("y:{}", y);

    let info = 10;
    println!("info:{}", info);

    println!("--------------------");
    for i in (1..5).rev() {
        println!("{}", i);
    }
    println!("--------------------");
    let begin = 1;
    let end = 5;
    for i in begin..end {
        println!("{}", i);
    }

    let a = Arc::new(Mutex::new(123));//线程安全版共享且内部可变

    let c = a.clone();
    let child1 = thread::spawn(move || { for _ in 0..COUNT { *c.lock().unwrap() += 2; } });

    let c = a.clone();
    let child2 = thread::spawn(move || { for _ in 0..COUNT { *c.lock().unwrap() -= 1; } });

    // 多任务同步
    child1.join().ok();
    child2.join().ok();
    println!("final:{:?}", a);

    let x = 1;
    let y = if x > 1 {
        10
    } else {
        20
    };
    println!("x:{},y:{}", x, y);

    let user_name = "admin";
    check_username(user_name.to_string());
    check_username2(user_name.to_string());

    hashmap();

    let mut info = String::from("张");
    info.push_str("学友");
    println!("{}", info);
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct TestStruct {
    data_int: u8,
    data_str: String,
    data_vector: Vec<u8>,
}

#[allow(dead_code)]
fn tt() {
    println!("os:{}", os());
    thread::sleep(Duration::from_secs(1));
    show_os();

    let a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
    let s = &a[2..8]; //切片结果中不包含end
    println!("{:?}", s);
    let s = &a[2..=8]; //切片结果中包含end
    println!("{:?}", s);

    let a = "rust developer";
    let s = &a[..6];
    println!("{}", s);

    let (id, job): (i32, String) = (1, "系统架构师".to_string());
    println!("id:{},job:{}", id, job);

    println!("FILE_NAME:{}", FILE_NAME);

    let mut v1: Vec<String> = Vec::new();
    v1.push("李小龙".to_string());
    v1.push("成龙".to_string());

    for i in &v1 {
        println!("{}", i)
    }

    let mut v2 = vec!["甄子丹", "吴京"];
    v2.push("abafd");
    for i in &v2 {
        println!("{}", i)
    }

    let star = &v2[0];
    println!("star:{}", star);

    match v2.get(0) {
        Some(_star) => println!("111"),
        None => println!("2222")
    }

    let object = TestStruct {
        data_int: 1,
        data_str: "homura".to_string(),
        data_vector: vec![2, 3, 4, 5],
    };

    // Serialize using `json::encode`
    // 将TestStruct转意为字符串
    let encoded = json::encode(&object).unwrap();
    println!("{}", encoded);
    // Deserialize using `json::decode`
    // 将json字符串中的数据转化成TestStruct对应的数据，相当于初始化
    let decoded: TestStruct = json::decode(&encoded).unwrap();
    println!("{:?}", decoded.data_vector);
}

#[allow(dead_code)]
fn save_user_info() {
    println!("{}", save(UserInfo { id: 1, user_name: "成龙".to_string(), password: Some("123456".to_string()) }));
}

#[allow(dead_code)]
fn delete_user_info_by_id(id: i32) {
    delete_by_id(id);
}

#[allow(dead_code)]
fn update_user_info_by_id(id: i32) {
    update_by_id(id, "刘德华".to_string());
}

#[allow(dead_code)]
fn query_user_info_by_id(id: i32) {
    let user_info_option = query_by_id(id);
    if !user_info_option.is_none() {
        let user_info = user_info_option.unwrap();
        println!("id:{},user_name:{},password:{}", user_info.id, user_info.user_name, user_info.password.as_deref().unwrap_or(""));
    }
}

#[allow(dead_code)]
fn check_user_info_login() {
    println!("{}", check_login("成龙".to_string(), "123456".to_string()));
    println!("{}", check_login("成龙".to_string(), "12345".to_string()));
}

#[allow(dead_code)]
fn query_all_user_info() {
    let user_infos = query_all();
    for user_info in user_infos.iter() {
        println!("id:{},user_name:{},password:{}", user_info.id, user_info.user_name, user_info.password.as_deref().unwrap_or(""));
    }
}

fn diverges() -> ! {
    panic!("This function never returns!");
}

#[allow(dead_code)]
fn test2(){
    let origin = UserInfo::default();
    let user_info = UserInfo {
        user_name: "刘德华".to_string(),
        ..origin
    };
    println!("{:?}", user_info);

    let x = 6;
    match x {
        _e @ 1..=5 => println!("number:{}", x),
        _ => println!("other number")
    }

    let u2 = UserInfo {
        id: 1,
        user_name: "张学友".to_string(),
        ..(UserInfo::default())
    };
    println!("{:?}", u2);

    enum OptionalInt {
        Value(i32),
        Missing,
    }

    let x = OptionalInt::Value(5);
    match x {
        OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"),
        OptionalInt::Value(..) => println!("Got an int!"),
        OptionalInt::Missing => println!("No such luck."),
    }

    let x = OptionalInt::Missing;
    match x {
        OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"),
        OptionalInt::Value(..) => println!("Got an int!"),
        OptionalInt::Missing => println!("No such luck."),
    }

    let a: UserInfo = UserInfo {
        id: 1,
        user_name: "张学友".to_string(),
        ..(UserInfo::default())
    };
    println!("{:?}", a);

    let b: crate::entity::user_info::UserInfo = UserInfo {
        id: 2,
        user_name: "张学友".to_string(),
        ..(UserInfo::default())
    };
    println!("{:?}", b);

    let number = Some(7);
    let mut optional = Some(0);

    if let Some(i) = number {
        println!("Matched {:?}!", i);
    } else {
        println!("Didn't match a number!");
    }

    while let Some(i) = optional {
        if i > 9 {
            println!("Greater than 9, quit!");
            optional = None;
        } else {
            println!("`i` is `{:?}`. Try again.", i);
            optional = Some(i + 1);
        }
    }

    println!("match:{}", regex());

    diverges();
}

fn main() {
    query_user_info_by_id(100);
//    check_user_info_login();
//    save_user_info();
}